/**
 * @file	halPeripheral.c
 * @author	chipsea
 * @brief	
 * @version	0.1
 * @date	2020-11-30
 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
 * @note
 */

/*********************************************************************
 * INCLUDES
 */
#include "sdk_config.h"
#include "log.h"
#include "key.h"
#include "OSAL.h"
#include "gpio.h"
#include "flash.h"
#include "clock.h"
#include "error.h"
#include "multi.h"
#include "pwrmgr.h"
#include "LL_def.h"
#include "multi_role.h"
#include "rom_sym_def.h"
#include "global_config.h"
#include "halPeripheral.h"


uint8_t Hal_TaskID;

user_data_t uart_rx_data;
//user_data_t uart_tx_data;

user_data_t ble_rx_data;
user_data_t ble_slave_rx_data;

uint8_t uart_send_buff[USER_BUF_SIZE];

/**
 * @fn      void HalPeripheral_Init(uint8 task_id)
 * @brief   Peripheral initialization
 * @param   task_id
 * @return  none
 */
void __ATTR_SECTION_SRAM__ uart_receive_callback(uart_Evt_t* pev)
{
	switch(pev->type)
	{
		case UART_EVT_TYPE_RX_DATA:
		case UART_EVT_TYPE_RX_DATA_TO:
		{
			uint8_t i;
            
			for(i=0; i<pev->len; i++)
            {
                if( (uart_rx_data.wr - uart_rx_data.rd) < USER_BUF_SIZE )
                {
                    uart_rx_data.data[(uart_rx_data.wr++)&USER_BUF_INDEX] = pev->data[i];
                }
                else
                {
//                    LOG("ble full\r\n");
                    break;
                }
			}
            peripheral_task_set(USER_TASK_START, USR_UART_RCV_DATA, 50);
		}
		break;
		
		case UART_EVT_TYPE_TX_COMPLETED:
//			LOG("tx completed\r\n");
		break;
	}
}

void ble_data_rec_evt(ble_data_evt_t* pev)
{
	switch(pev->ev){
        case BLE_EVT_TX_NOTI_DISABLED:
            
        break;
        
        case BLE_EVT_TX_NOTI_ENABLED:
            //LOG("BUP_OSAL_EVT_NOTIFY_DATA\n");
        break;
        
        case BLE_EVT_BLE_DATA_RECIEVED:
//            LOG("ble rec:");
            if(pev->role == ROLE_SLAVE)
            {
                for(uint8 i=0; i<pev->param; i++)
                {
                    if( (ble_rx_data.wr - ble_rx_data.rd) < USER_BUF_SIZE )
                    {
                        ble_rx_data.data[(ble_rx_data.wr++)&USER_BUF_INDEX] = pev->data[i];
                    }
                    else
                    {
                        LOG("f");
                        break;
                    }
                    peripheral_task_set(USER_TASK_START, USR_BLE_RCV_DATA, 50);
    //                LOG("%x ", pev->data[i]);
                }
            }
            else
            {
                for(uint8 i=0; i<pev->param; i++)
                {
                    if( (ble_slave_rx_data.wr - ble_slave_rx_data.rd) < USER_BUF_SIZE )
                    {
                        ble_slave_rx_data.data[(ble_slave_rx_data.wr++)&USER_BUF_INDEX] = pev->data[i];
                    }
                    else
                    {
                        LOG("f");
                        break;
                    }
                    peripheral_task_set(USER_TASK_START, USR_BLE_SLAVE_RCV_DATA, 50);
    //                LOG("%x ", pev->data[i]);
                }
            }
//            LOG("\r\n");
        break;
        
        default:
        
        break;
	}
}

/**
 * @fn      void HalPeripheral_Init(uint8 task_id)
 * @brief   Peripheral initialization
 * @param   task_id
 * @return  none
 */
void HalPeripheral_Init(uint8 task_id)
{
	Hal_TaskID = task_id;
    
    HalGpioPinInit(BT_STATUS_PIN, GPIO_OUTPUT);
    HalGpioSet(BT_STATUS_PIN, Bit_ENABLE);
    
//    uart_Cfg_t cfg = {
//		.tx_pin = P20,
//		.rx_pin = P18,
//		.baudrate = 115200,
//		.use_fifo = TRUE,
//		.hw_fwctrl = FALSE,
//		.use_tx_buf = TRUE,
//		.parity     = FALSE,
//		.evt_handler = uart_receive_callback,
//	};
//	HalUartInit(UART1, cfg);//uart init
//    HalUartSetTxBuf(UART1, uart_send_buff, UART_BUF_SIZE);
    
    bleuart_AddService(ble_data_rec_evt);
    
//    osal_memcpy(uart_send_buf, "OK\r\n", 4);
//    HalUartSendBuf(UART1, uart_send_buf, 4);
    
    HalUartRegister(UART0, uart_receive_callback);
    
    osal_start_reload_timer(Hal_TaskID, USR_CONNECT_LED, 1000);
}

void send_data_to_ble(uint8_t role, uint16_t events, user_data_t *data)
{
    uint8_t len;
    attMsg_t sendMsg;
    
    if(data->wr != data->rd)
    {
        if(LL_ROLE_MASTER == role)
        {
            len = ATT_GetCurrentMTUSize(masterPeerConnectionInfo[0].ConnectionHandle);
        }
        else
        {
            len = ATT_GetCurrentMTUSize(masterDevInfo[0].ConnectionHandle);
        }
        
        if( len > (data->wr-data->rd) )
        {
            len = data->wr-data->rd;
        }
        for(uint8 i=0; i<len; i++)
        {
            sendMsg.writeReq.value[i] = data->data[(data->rd++)&USER_BUF_INDEX];
        }
        sendMsg.writeReq.len = len;
        
        user_data_send_by_ble(role, 0, &sendMsg);
    }
    if(data->wr != data->rd)
    {
        peripheral_task_set(USER_TASK_START, events, 50);
    }
}

/**
 * @fn      uint16 HalPeripheral_ProcessEvent( uint8 task_id, uint16 events )
 * @brief   Peripheral event process
 * @param   task_id
 * @param	events
 * @return  none
 */
uint16 HalPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{
	if(task_id != Hal_TaskID)
    {
		return 0;
	}
	
	if( events & USR_UART_RCV_DATA )
    {
        send_data_to_ble(LL_ROLE_MASTER, USR_UART_RCV_DATA, &uart_rx_data);
		
        return ( events ^ USR_UART_RCV_DATA );
    }
    
    if( events & USR_BLE_RCV_DATA )
    {
        send_data_to_ble(LL_ROLE_MASTER, USR_BLE_RCV_DATA, &ble_rx_data);
		
        return ( events ^ USR_BLE_RCV_DATA );
    }
    
    if( events & USR_BLE_SLAVE_RCV_DATA )
    {
        send_data_to_ble(LL_ROLE_SLAVE, USR_BLE_SLAVE_RCV_DATA, &ble_slave_rx_data);
        return ( events ^ USR_BLE_SLAVE_RCV_DATA );
    }
    
    if( events & USR_CONNECT_LED)
    {
        if(g_masterConnectNum && g_masterConnectNum)
        {
            HalGpioSet(BT_STATUS_PIN, Bit_DISABLE);
        }
        else
        {
            uint8_t status;
            
            status = HalGpioGet(BT_STATUS_PIN);
            HalGpioSet(BT_STATUS_PIN, (bit_action_e)(!status));
        }
        return ( events ^ USR_CONNECT_LED );
    }
	
    // Discard unknown events
    return 0;
}

/**
 * @fn		void peripheral_task_set(uint8 action, uint16 event, uint32 time)
 * @brief	
 * @param	none
 * @return	none
 */
void peripheral_task_set(uint8 action, uint16 event, uint32 time)
{
    osal_stop_timerEx(Hal_TaskID, event);
    if(action == USER_TASK_START)
    {
        if(time)
        {
            osal_start_timerEx(Hal_TaskID, event, time);
        }
        else
        {
            osal_set_event(Hal_TaskID, event);
        }
    }
}

/*********************************************************************
*********************************************************************/
